/*
 * 描          述:  <描述>
 * 修  改   人:  Administrator
 * 修改时间:  2019年12月11日
 * <修改描述:>
 */
package com.tx.component.social.support.weibo;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import com.tx.component.security.exception.SocialAuthorizeException;
import com.tx.component.social.SocialLoginPlugin;
import com.tx.component.social.context.SocialLoginContext;
import com.tx.component.social.model.SocialAccountType;
import com.tx.component.social.model.SocialAccountTypeEnum;
import com.tx.core.exceptions.util.AssertUtils;
import com.tx.core.util.MessageUtils;

import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.config.AuthConfig.AuthConfigBuilder;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthDefaultRequest;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.request.AuthWeiboRequest;

/**
 * 微信登陆插件<br/>
 * OAuth2.0错误响应中的错误码定义如下表所示：
 * https://open.weibo.com/wiki/%E6%8E%88%E6%9D%83%E6%9C%BA%E5%88%B6%E8%AF%B4%E6%98%8E#.E5.8F.96.E6.B6.88.E6.8E.88.E6.9D.83.E5.9B.9E.E8.B0.83.E9.A1.B5
 * https://open.weibo.com/apps/571926088/info/advanced 修改Oauth2授权设置，在该页设置回调页地址
 * 
 * 错误码(error)  错误编号(error_code)    错误描述(error_description)
 * redirect_uri_mismatch   21322   重定向地址不匹配
 * invalid_request 21323   请求不合法
 * invalid_client  21324   client_id或client_secret参数无效
 * invalid_grant   21325   提供的Access Grant是无效的、过期的或已撤销的
 * unauthorized_client 21326   客户端没有权限
 * expired_token   21327   token过期
 * unsupported_grant_type  21328   不支持的 GrantType
 * unsupported_response_type   21329   不支持的 ResponseType
 * access_denied   21330   用户或授权服务器拒绝授予数据访问权限
 * temporarily_unavailable 21331   服务暂时无法访问
 * appkey permission denied    21337   应用权限不足
 * 
 * @author  Administrator
 * @version  [版本号, 2019年12月11日]
 * @see  [相关类/方法]
 * @since  [产品/模块版本]
 */
public class WBLoginPlugin extends SocialLoginPlugin<WBLoginPluginConfig> {
    
    ///** code请求URL */
    //private static final String CODE_REQUEST_URL = "https://api.weibo.com/oauth2/authorize";
    //
    ///** uid请求URL */
    //private static final String UID_REQUEST_URL = "https://api.weibo.com/oauth2/access_token";
    //
    ///** userInfo请求URL */
    //private static final String USER_INFO_REQUEST_URL = "https://api.weibo.com/2/users/show.json";
    
    /** "状态"属性名称 */
    private static final String REDIRECT_URL_ATTRIBUTE_NAME = WBLoginPlugin.class
            .getName() + ".REDIRECT_URL";
    
    /**
     * @return
     */
    @Override
    public String getName() {
        return "微博登陆插件";
    }
    
    /**
     * @return
     */
    @Override
    public String getVersion() {
        return "1.0";
    }
    
    /**
     * @return
     */
    @Override
    public SocialAccountType getSocialAccountType() {
        return SocialAccountTypeEnum.WB;
    }
    
    /**
     * @return
     */
    @Override
    public String getPrefix() {
        return "plugin.login.wb";
    }
    
    /**
     * 获取code的handle<br/>
     * @param viewName
     * @param redirectUri
     * @param scope
     * @param request
     * @return
     */
    @Override
    public String authorize(String redirectUri, String state,
            List<String> scopes, HttpServletRequest request) {
        AssertUtils.notEmpty(redirectUri, "redirectUri is empty.");
        
        //写入state值
        HttpSession session = request.getSession();
        SocialLoginContext.getContext().saveState(session, state);
        session.setAttribute(REDIRECT_URL_ATTRIBUTE_NAME, redirectUri);
        
        WBLoginPluginConfig config = getConfig();
        AuthConfigBuilder acbuilder = AuthConfig.builder()
                .clientId(config.getAppKey())
                .clientSecret(config.getAppSecret())
                .redirectUri(redirectUri);
        if (!CollectionUtils.isEmpty(scopes)) {
            acbuilder.scopes(scopes);
        }
        AuthRequest authRequest = new AuthWeiboRequest(acbuilder.build());
        String authorize = authRequest.authorize(state);
        return authorize;
    }
    
    /**
     * @param code
     * @param state
     * @param request
     * @return
     * @throws SocialAuthorizeException
     */
    @Override
    public AuthUser login(String code, String state, HttpServletRequest request)
            throws SocialAuthorizeException {
        HttpSession session = request.getSession();
        String sessionState = SocialLoginContext.getContext().getState(session);
        if (!StringUtils.equals(state, sessionState)) {
            throw new SocialAuthorizeException(MessageUtils.format(
                    "state value is invalid.request_state:{}  session_state:{}",
                    state,
                    sessionState));
        }
        
        WBLoginPluginConfig config = getConfig();
        AuthConfigBuilder acbuilder = AuthConfig.builder()
                .clientId(config.getAppKey())
                .clientSecret(config.getAppSecret());
        AuthDefaultRequest authRequest = new AuthWeiboRequest(
                acbuilder.ignoreCheckState(true).build());
        
        @SuppressWarnings("unchecked")
        AuthResponse<AuthUser> resp = authRequest
                .login(AuthCallback.builder().code(code).build());
        if (!resp.ok()) {
            throw new SocialAuthorizeException("获取第三方登陆用户信息失败.");
        }
        
        AuthUser au = resp.getData();
        return au;
    }
    
    ///**
    // * 获取code的handle<br/>
    // * @param viewName
    // * @param redirectUri
    // * @param scope
    // * @param request
    // * @return
    // */
    //@Override
    //public ModelAndView generateCodeModelView(String viewName,
    //        String redirectUri, String state, String scope,
    //        HttpServletRequest request) {
    //    AssertUtils.notEmpty(redirectUri, "redirectUri is empty.");
    //    
    //    //写入state值
    //    HttpSession session = request.getSession();
    //    SocialLoginContext.getContext().saveState(session, state);
    //    session.setAttribute(REDIRECT_URL_ATTRIBUTE_NAME, redirectUri);
    //    
    //    WBLoginPluginConfig config = getConfig();
    //    ModelAndView mview = new ModelAndView();
    //    
    //    Map<String, String> parameterMap = new LinkedHashMap<>();
    //    parameterMap.put("response_type", "code");
    //    parameterMap.put("client_id", config.getAppKey());
    //    parameterMap.put("redirect_uri", redirectUri);
    //    parameterMap.put("state", state);
    //    
    //    //mview.addObject("requestUrl", CODE_REQUEST_URL);
    //    //mview.addObject("parameterMap", parameterMap);
    //    //mview.setViewName(viewName);
    //    
    //    List<NameValuePair> nameValuePairs = new ArrayList<>();
    //    for (Entry<String, String> entryTemp : parameterMap.entrySet()) {
    //        if (StringUtils.isEmpty(entryTemp.getKey())) {
    //            continue;
    //        }
    //        nameValuePairs.add(new BasicNameValuePair(entryTemp.getKey(),
    //                entryTemp.getValue()));
    //    }
    //    String url = CODE_REQUEST_URL;
    //    try {
    //        url = url + (StringUtils.contains(url, "?") ? "&" : "?")
    //                + EntityUtils.toString(
    //                        new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
    //    } catch (ParseException | IOException e) {
    //        throw new SILException("拼接redirectUrl异常.", e);
    //    }
    //    //生成视图逻辑
    //    if (StringUtils.isEmpty(viewName)) {
    //        mview.setViewName("redirect:" + url);
    //    } else {
    //        mview.setViewName(viewName);
    //    }
    //    return mview;
    //}
    //
    ///**
    // * 获取AccessToken<br/>
    // *      https://open.weibo.com/wiki/Oauth/access_token
    // * <功能详细描述>
    // * @param request
    // * @param response
    // * @return
    // * @throws Exception [参数说明]
    // * 
    // * @return boolean [返回类型说明]
    // * @exception throws [异常类型] [异常说明]
    // * @see [类、类#方法、类#成员]
    // */
    //@Override
    //public SocialAccessToken getAccessToken(String code, String state,
    //        HttpServletRequest request) throws SocialAuthorizeException {
    //    HttpSession session = request.getSession();
    //    String sessionState = SocialLoginContext.getContext().getState(session);
    //    if (!StringUtils.equals(state, sessionState)) {
    //        throw new SocialAuthorizeException(MessageUtils.format(
    //                "state value is invalid.request_state:{}  session_state:{}",
    //                state,
    //                sessionState));
    //    }
    //    
    //    //从会话中获取redirectUri
    //    String redirectUri = (String) session
    //            .getAttribute(REDIRECT_URL_ATTRIBUTE_NAME);
    //    
    //    WBLoginPluginConfig config = getConfig();
    //    Map<String, String> parameterMap = new HashMap<>();
    //    parameterMap.put("grant_type", "authorization_code");
    //    String appKey = config.getAppKey();
    //    String appSecret = config.getAppSecret();
    //    parameterMap.put("client_id", appKey);
    //    parameterMap.put("client_secret", appSecret);
    //    parameterMap.put("code", code);
    //    parameterMap.put("redirect_uri", redirectUri);
    //    String result = HttpClientUtils.post(UID_REQUEST_URL, parameterMap);
    //    logger.info(
    //            "--- getAccessToken:{client_id:{},client_secret:{},code:{},result:{}}",
    //            appKey,
    //            appSecret,
    //            code,
    //            result);
    //    //{"access_token":"2.00zleWPB01Gkhc5cc927db85Da_qIB","remind_in":"157679999","expires_in":157679999,"uid":"1145561103","isRealName":"true"}
    //    JsonNode node = JsonUtils.toTree(result);
    //    String accessToken = node.get("access_token").textValue();
    //    String uid = node.get("uid").textValue();
    //    
    //    SocialAccessToken token = new SocialAccessToken(
    //            SocialAccountTypeEnum.WB);
    //    token.setExpiresIn((new Date()).getTime() + 10 * 60 * 1000);
    //    token.setUniqueId(uid);
    //    token.setAccessToken(accessToken);
    //    //token.setExpiresIn(node.get("expires_in").longValue());
    //    token.getAttributeJSONObject()
    //            .put("remind_in", node.get("remind_in").longValue());
    //    token.getAttributeJSONObject()
    //            .put("isRealName", node.get("isRealName").booleanValue());
    //    if (StringUtils.isEmpty(token.getUniqueId())) {
    //        throw new SocialAuthorizeException("获取UniqueId失败.");
    //    }
    //    if (StringUtils.isEmpty(token.getAccessToken())) {
    //        throw new SocialAuthorizeException("获取AccessToken失败.");
    //    }
    //    return token;
    //}
    //
    ///**
    // * 获取用户信息<br/>
    // * <功能详细描述>
    // * @param accessToken
    // * @param request
    // * @return [参数说明]
    // * 
    // * @return LoginUserInfo [返回类型说明]
    // * @exception throws [异常类型] [异常说明]
    // * @see [类、类#方法、类#成员]
    // */
    //@Override
    //public SocialUserInfo getUserInfo(SocialAccessToken accessToken,
    //        HttpServletRequest request) {
    //    AssertUtils.notNull(accessToken, "accessToken is null.");
    //    AssertUtils.notEmpty(accessToken.getUniqueId(),
    //            "accessToken.uniqueId is empty.");
    //    AssertUtils.notEmpty(accessToken.getAccessToken(),
    //            "accessToken.accessToken is empty.");
    //    
    //    Map<String, String> params = new HashMap<String, String>();
    //    params.put("access_token", accessToken.getAccessToken());
    //    params.put("uid", accessToken.getUniqueId());
    //    String result = HttpClientUtils.get(USER_INFO_REQUEST_URL, params);
    //    logger.info("--- getUserInfo:{access_token:{},openid:{},result:{}}",
    //            accessToken.getAccessToken(),
    //            accessToken.getUniqueId(),
    //            result);
    //    
    //    JsonNode node = JsonUtils.toTree(result);
    //    SocialUserInfo user = new SocialUserInfo();
    //    user.setId(node.get("id").asText());
    //    user.setSocialUsername(node.get("name").asText());
    //    user.setSex(StringUtils.equalsAnyIgnoreCase("m",
    //            node.get("gender").asText()) ? SexEnum.MALE : SexEnum.FEMALE);
    //    user.setUniqueId(accessToken.getUniqueId());
    //    user.setHeadImgUrl(node.get("profile_image_url").asText());
    //    JSONObject json = user.getAttributeJSONObject();
    //    json.put("screen_name", node.get("screen_name").asText());
    //    json.put("domain", node.get("domain").asText());
    //    json.put("province", node.get("province").asText());
    //    json.put("city", node.get("city").asText());
    //    json.put("location", node.get("location").asText());
    //    json.put("description", node.get("description").asText());
    //    json.put("url", node.get("url").asText());
    //    return user;
    //}
    //
    ///**
    // * 获取登陆用户的第三方唯一键<br/>
    // * @param code
    // * @param state
    // * @param request
    // * @return
    // * @throws SocialAuthorizeException
    // */
    //@Override
    //public String getUniqueId(SocialAccessToken accessToken,
    //        HttpServletRequest request) throws SocialAuthorizeException {
    //    AssertUtils.notNull(accessToken, "accessToken is null.");
    //    AssertUtils.notEmpty(accessToken.getUniqueId(),
    //            "accessToken.uniqueId is empty.");
    //    AssertUtils.notEmpty(accessToken.getAccessToken(),
    //            "accessToken.accessToken is empty.");
    //    
    //    String uniqueId = accessToken.getUniqueId();
    //    return uniqueId;
    //}
    
}
